// 类型查询操作符 : 熟悉又陌生的 typeof
const str1 = "azyyz";
const obj2 = { name1: "azyyz" };
const nullVarOne: null = null;
const undefinedVarOne: null = undefined;

const funcOne = (input: string) => {
  return input.length > 10;
};

type Str1 = typeof str1; // "azyyz"
type Obj2 = typeof obj2; // "{ name1: "azyyz" }"
type Null = typeof nullVarOne; // "null"
type Undefined = typeof undefinedVarOne; // undefined
type Func1 = typeof funcOne; // { (input: string) => boolean }

const funcOne1 = (input: string) => {
  return input.length > 10;
};

const funcTwo2: typeof funcOne1 = (name: string) => {
  return name === "azyyz";
};
// ReturnType 检测这个function的类型 幷返回;
type FuncReturnType = ReturnType<typeof funcOne1>;


// 类型守卫 返回函数内类型(支流) 收集这些支流的类型返回
function Faker (LOLInput:string | number) {
    if(typeof LOLInput === "string") {}
    if(typeof LOLInput === "number") {}
}

// nerver 
declare const strOrNumOrBool: string | number | boolean;

if(typeof strOrNumOrBool === "string") {
    // 一定是字符串!
    strOrNumOrBool.charAt(1);
}else if (typeof strOrNumOrBool === "number") {
    // 一定是数字!
    strOrNumOrBool.toFixed();
}else if (typeof strOrNumOrBool === "boolean") {
    // 一定是布尔值!
    strOrNumOrBool === true;
} else {
    // 走到这里,说明类型有问题, 抛出异常
    const _exhaustiveCheck: never= strOrNumOrBool;
    throw new Error(`Unknown input type: ${_exhaustiveCheck}`);
}

// 类型保护;
function isString(input: unknown):boolean{
    return typeof input === "string";
}
function deft (input:string | number) {
    if(isString(input)) {
        // 正确了
        // (input).replace("azyyz","azyyz998");
    }
    if(typeof input=== "number"){

    }
}
function isString2(input:unknown) : input is string {
    return typeof input === "string";
}
function Foo3(input:string | number) {
    if(isString2(input)) {
        // 正确了
        (input).replace("azyyz","azyyz998")
    }
    if(typeof input === "number") {
        
    }
}
// 导出 这个接口
export type Falsy = false | "" | 0 | null | undefined;

export const isFalsy = (val:unknown): val is Falsy => !val;

// 不包括不常用的 symbol 和 bigint
export type Primitive = string | number | boolean | undefined;
// 传入的值类型是否满足 Primitive 中的其中一个类型 使用includes 返回布尔值;
export const isPrimive = (val: unknown) : val is Primitive => ['string', 'number', 'boolean', 'undefined'].includes(typeof val);

// 类型断言守卫:
// NoedeJs assert 模块, 
import assert from 'assert';

let name: any = "azyyz";

assert(typeof name === "number");

// number 类型
// toFixed 四舍五入;
name.toFixed();

function assert(condition: any,msg?: string): asserts condition{
    if(!condition) {
        throw new Error(msg);
    }
}

let name1:any = "azyyzaz";

function assertIsNumber(val:any): asserts val is number {
    if(typeof val !== 'number') {
        throw new Error('Not a number');
    }
}
assertIsNumber(name1);

name1.toFixed();
